package org.webcat.electronicsubmissionplugin.model;

/**
 * Used to spawn a LRT. Must call startTask to begin.
 *
 * @author rob44, rstodd13, samccarn
 */
public abstract class LongRunningTask
{

    private volatile Thread blinker;
    private boolean         success;


    /**
     * Method called to execute the task.
     */
    public void startTask()
    {

        Thread myThread = new Thread() {

            @Override
            public void run()
            {
                beforeStart();
                Thread thisThread = Thread.currentThread();
                while (thisThread == blinker)
                {
                    try
                    {
                        taskToRun();
                        success = true;
                    }
                    catch (Exception ex)
                    {
                        onError(ex);
                        success = false;
                    }
                    finally
                    {
                        if (success)
                        {
                            onSuccessfulComplete();
                        }
                        else
                        {
                            onErrorComplete();
                        }

                        endTask();
                    }
                }

            }
        };

        blinker = new Thread(myThread);
        blinker.start();

    }


    /**
     * Task to be run.
     *
     * @throws Exception
     *             the exception
     */
    public abstract void taskToRun()
        throws Exception;


    /**
     * What to do on error execution.
     *
     * @param ex
     *            the ex
     */
    public abstract void onError(Exception ex);


    /**
     * Executed on successful complete.
     */
    public abstract void onSuccessfulComplete();


    /**
     * Executed on error complete. Convenience method.
     */
    public void onErrorComplete()
    {
        // does nothing, but not required to do anything
    }


    /**
     * Executed before the start of the task.
     */
    public abstract void beforeStart();


    /**
     * Ends this task.
     */
    public void endTask()
    {
        blinker = null;
    }
}
